﻿using DSF.Net.Controllers.Theme;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DSF.Net.Controllers.Process
{
    /// <summary>
    /// VertiProcessFull.xaml 的交互逻辑
    /// </summary>
    public partial class VertiProcessFull : UserControl,IUserTheme
    {
        public VertiProcessFull()
        {
            InitializeComponent();
            Value = 0;
            DataContext = this;
        }

        readonly double pointerPos = 59;
        readonly double barLenth = 50;



        public double Limit
        {
            get { return (double)GetValue(LimitProperty); }
            set { SetValue(LimitProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Limit.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LimitProperty =
            DependencyProperty.Register("Limit", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(10d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var limit = (double)e.NewValue;
                c.ValueGrid.Margin = new Thickness(c.ValueGrid.Margin.Left, c.pointerPos - c.Value / limit * c.barLenth, c.ValueGrid.Margin.Right, c.ValueGrid.Margin.Bottom);
                if (c.Value > 0)
                {
                    c.blueRec.Height = c.barLenth * c.Value / limit;
                }
                else if (c.Value < 0)
                {
                    c.orangeRec.Height = c.barLenth * -c.Value / limit;
                }
            }));

        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(0d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var oldValue = (double)e.OldValue;
                var newValue = (double)e.NewValue;
                var pointerAnimation = new DoubleAnimation
                {
                    From = oldValue,
                    To = newValue,
                    Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300)),
                    EasingFunction = new QuadraticEase()
                };
                c.BeginAnimation(PointerAnimateProperty, pointerAnimation);
                c.BeginAnimation(TextAnimateProperty, pointerAnimation);
                if (oldValue >= 0 && newValue >= 0)
                {
                    var animation = new DoubleAnimation
                    {
                        From = oldValue,
                        To = newValue,
                        Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300)),
                        EasingFunction = new QuadraticEase()
                    };
                    c.BeginAnimation(BlueBarAnimateProperty, animation);
                }
                else if (oldValue <= 0 && newValue <= 0)
                {
                    var animation = new DoubleAnimation
                    {
                        From = -oldValue,
                        To = -newValue,
                        Duration = new Duration(new TimeSpan(0, 0, 0, 0, 300)),
                        EasingFunction = new QuadraticEase()
                    };
                    c.BeginAnimation(YellowBarAnimateProperty, animation);
                }
                else
                {
                    var blueAnimation = new DoubleAnimation
                    {
                        From = newValue > 0 ? 0 : oldValue,
                        To = newValue > 0 ? newValue : 0,
                        Duration = new Duration(new TimeSpan(0, 0, 0, 0, 150)),
                        EasingFunction = new QuadraticEase()
                    };
                    var yellowAnimation = new DoubleAnimation
                    {
                        From = oldValue > 0 ? 0 : -oldValue,
                        To = oldValue > 0 ? -newValue : 0,
                        Duration = new Duration(new TimeSpan(0, 0, 0, 0, 150)),
                        EasingFunction = new QuadraticEase()
                    };
                    if (newValue > 0)
                    {
                        yellowAnimation.Completed += (o, t) =>
                        {
                            c.BeginAnimation(BlueBarAnimateProperty, blueAnimation);
                        };
                        c.BeginAnimation(YellowBarAnimateProperty, yellowAnimation);
                    }
                    else
                    {
                        blueAnimation.Completed += (o, t) =>
                        {
                            c.BeginAnimation(YellowBarAnimateProperty, yellowAnimation);
                        };
                        c.BeginAnimation(BlueBarAnimateProperty, blueAnimation);
                    }
                }
                
            }));



        public int Precision
        {
            get { return (int)GetValue(PrecisionProperty); }
            set { SetValue(PrecisionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Precision.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PrecisionProperty =
            DependencyProperty.Register("Precision", typeof(int), typeof(VertiProcessFull), new PropertyMetadata(3, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var value = (int)e.NewValue;
                var priciseStr = new StringBuilder("#0.");
                for (var i = 0; i < value; i++)
                {
                    priciseStr.Append('0');
                }
                c.ValueLabel.Content = c.Value.ToString(priciseStr.ToString());
            }));

        private static readonly DependencyProperty BlueBarAnimateProperty =
            DependencyProperty.Register("BlueBarAnimate", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(0d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var value = (double)e.NewValue;
                c.blueRec.Height = c.barLenth * value / c.Limit;
            }));

        private static readonly DependencyProperty YellowBarAnimateProperty =
            DependencyProperty.Register("YellowBarAnimate", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(0d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var value = (double)e.NewValue;
                c.orangeRec.Height = c.barLenth * value / c.Limit;
            }));
        private static readonly DependencyProperty PointerAnimateProperty =
            DependencyProperty.Register("PointerAnimate", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(0d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var value = (double)e.NewValue;
                c.ValueGrid.Margin = new Thickness(c.ValueGrid.Margin.Left, c.pointerPos - value / c.Limit * c.barLenth, c.ValueGrid.Margin.Right, c.ValueGrid.Margin.Bottom);
            }));
        private static readonly DependencyProperty TextAnimateProperty =
            DependencyProperty.Register("TextAnimate", typeof(double), typeof(VertiProcessFull), new PropertyMetadata(0d, (s, e) =>
            {
                var c = s as VertiProcessFull;
                var value = (double)e.NewValue;
                var priciseStr = new StringBuilder("#0.");
                for (var i = 0; i < c.Precision; i++)
                {
                    priciseStr.Append('0');
                }
                c.ValueLabel.Content = value.ToString(priciseStr.ToString());
            }));

        public Theme.Colors ThemeColor
        {
            get { return (Theme.Colors)GetValue(ThemeColorProperty); }
            set { SetValue(ThemeColorProperty, value); }
        }

        public static readonly DependencyProperty ThemeColorProperty =
            DependencyProperty.Register("ThemeColor", typeof(Theme.Colors), typeof(VertiProcessFull), new PropertyMetadata(Theme.Colors.Default));

    }
}
